#ifndef __M__CONNECTION_H_
#define __M__CONNECTION_H_

#include "channel.hpp"

namespace mq
{
    // 连接类：对该连接所对应的信道增删改
    class Connection
    {
    public:
        using ptr = shared_ptr<Connection>;
        Connection(const ConsumerManager::ptr &cmp,
                   const TcpConnectionPtr &conn,
                   const ProtobufCodecPtr &codec,
                   const VirtualHost::ptr &host,
                   const ThreadPool::ptr &tpool)
            : _cm(make_shared<ChannelManager>()), _cmp(cmp), _conn(conn), _codec(codec), _host(host), _tpool(tpool) {}
        ~Connection() {}
        void openChannel(const openChannelRequestPtr &req) // 打开信道
        {
            string open_cid = req->cid();
            bool ret = _cm->openChanel(open_cid, _cmp, _conn, _codec, _host, _tpool);
            if (!ret) // 该信道已经被打开过了
            {
                DLOG("信道重复打开：%s", open_cid.c_str());
                basicResponse(req->rid(), open_cid, false);
                return;
            }
            else
                DLOG("打开信道成功:cid %s", open_cid.c_str());
            basicResponse(req->rid(), open_cid, true);
        }
        void closeChannel(const closeChannelRequestPtr &req) // 关闭信道
        {
            string close_cid = req->cid();
            _cm->closeChannel(close_cid);
            basicResponse(req->rid(), close_cid, true);
        }
        Channel::ptr getChannel(const string &cid)
        {
            return _cm->getChannel(cid);
        }

    private:
        void basicResponse(const string &rid, const string &cid, bool ok)
        {
            // 构建响应并发回
            basicCommonResponse resp;
            resp.set_rid(rid);
            resp.set_cid(cid);
            resp.set_ok(ok);
            _codec->send(_conn, resp);
        }

    private:
        ChannelManager::ptr _cm; // 信道管理句柄

        // 信道需要什么资源，就需要管理什么资源：
        ConsumerManager::ptr _cmp;          // 消费者管理句柄
        muduo::net::TcpConnectionPtr _conn; // 网络通信所用连接
        ProtobufCodecPtr _codec;            // protobuf协议处理句柄
        VirtualHost::ptr _host;             // 虚拟机句柄
        ThreadPool::ptr _tpool;             // 工作线程池句柄
    };

    // 连接管理类
    class ConnectionManager
    {
    public:
        using ptr = shared_ptr<ConnectionManager>;
        ConnectionManager() {}
        void newConnection(const ConsumerManager::ptr &cmp,
                           const TcpConnectionPtr &conn,
                           const ProtobufCodecPtr &codec,
                           const VirtualHost::ptr &host,
                           const ThreadPool::ptr &tpool) // 创建连接
        {
            unique_lock<mutex> lock(mtx);
            auto it = _connections.find(conn);
            if (it != _connections.end())
                return;
            auto self_conn = make_shared<Connection>(cmp, conn, codec, host, tpool);
            _connections.insert(make_pair(conn, self_conn));
        }
        void delConnection(const TcpConnectionPtr &conn) // 关闭连接
        {
            unique_lock<mutex> lock(mtx);
            _connections.erase(conn);
        }
        Connection::ptr getConnection(const TcpConnectionPtr &conn) // 获取连接
        {
            unique_lock<mutex> lock(mtx);
            auto it = _connections.find(conn);
            if (it == _connections.end())
                return Connection::ptr();
            return it->second;
        }

    private:
        mutex mtx;
        unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _connections;
        // muduo库中连接与自定义connection类的映射
    };
};

#endif